#include "Interface.h"
#include "../Game.h"

Interface::Interface(int width, int height, int bitsPerPixel, Uint32 flags) {
	this->width = width;
	this->height = height;
	this->bitsPerPixel = bitsPerPixel;
	this->flags = flags;

	this->screen = 0;
	this->interfaceSurface = 0;
	this->downButton = b_none;

	this->activeScreen = s_world;
	this->inventoryScreen = 0;
	this->font = 0;
	this->world = 0;
}

bool Interface::Init() {
	//wczytuję wymiary blitów
	ifstream file("data/interface");
	if (!file.is_open()) {
		return DebugMessage("Interface", "Init", "Can't load blits!", warning);
	}
	int count;
	file >> count;
	for (int i = 0; i < count; ++i) {
		string name;
		SDL_Rect rect;
		file >> name >> rect.x >> rect.y >> rect.w >> rect.h;
		blits[name] = rect;
	}

	if (TTF_Init()) {
		return DebugMessage("Interface", "Init", TTF_GetError(), error);
	}

	if (!(font = TTF_OpenFont("img/font.ttf", 30))) {
		return DebugMessage("Interface", "Init", TTF_GetError(), error);
	}

	if (!screen) {
		if (SDL_Init(SDL_INIT_TIMER|SDL_INIT_AUDIO|SDL_INIT_VIDEO) == -1)
			return DebugMessageSDL("Interface", "Init", error);

		screen = SDL_SetVideoMode(width, height, bitsPerPixel, flags);

		if (!screen)
			return DebugMessageSDL("Interface", "Init", error);

		inventoryScreen = new InventoryScreen(screen, font, blits);
	} else {
		return DebugMessage("Interface", "Init", "Run DeInit first!", warning);
	}

	world = new World("data/config", screen, 0, 0);
	return true;
}

void Interface::DeInit() {
	//zwalniamy czcionkę
	if (font)
		TTF_CloseFont(font);

	//zwalniamy świat
	if (world)
		delete world;
	world = 0;

	//zwalniamy ekran ekwipunku
	if (inventoryScreen)
		delete inventoryScreen;
	inventoryScreen = 0;

	//zwalniamy wczytany obrazek interfejsu
	if (interfaceSurface)
		SDL_FreeSurface(interfaceSurface);
	interfaceSurface = 0;

	//zwalniamy ekran
	if (screen)
		SDL_FreeSurface(screen);
	screen = 0;

	SDL_Quit();
}

bool Interface::Draw(bool drawCentre) {
	if (!interfaceSurface) {
		if (!(interfaceSurface = IMG_Load("img/interface.png"))) {
			DebugMessage("Interface", "Draw", "Couldn't load interface file!", error);
			return false;
		}
	}
	
	if (drawCentre && !DrawCentre())
		return false;

	if (Game::GetInstance().isPaused && activeScreen == s_world) {
		WriteText("Paused", screen, font, 500, 330, 0xFF, 0xFF, 0xFF);
	}

	//współrzędne wyznaczone raczej metodą prób i błędów

	//dół
	DisplaySurface(interfaceSurface, 0, 646, blits["interface"]);

	//bok
	DisplaySurface(world->player->activeWeapon->image, 185, 710, 0, 0, 34, 34);
	DisplaySurface(world->player->activeArmor->image, 260, 710, 0, 0, 34, 34);

	//pasek życia
	float a = (float)world->player->life/(float)world->player->getMaxLife();
	//DisplaySurface(interfaceSurface, 50, 250 + 110 * (1 - a), 230, 282 + 110 * (1 - a), 24, 110 * a);
	DisplaySurface(interfaceSurface, 36, 735, blits["lifeBar"].x, blits["lifeBar"].y, blits["lifeBar"].w * a, blits["lifeBar"].h);

	//pasek exp
	int* levels = world->player->getExpLevels();
	int exp = world->player->exp;
	a = (float)(exp - levels[world->player->level - 1]) / (float)(levels[world->player->level] - levels[world->player->level - 1]);
	DisplaySurface(interfaceSurface, 36, 697, blits["expBar"].x, blits["expBar"].y, blits["expBar"].w * a, blits["expBar"].h);

	//ekwipunek
	DisplaySurface(interfaceSurface, 450, 690, blits["button"]);
	if (downButton == b_inventory)
		DisplaySurface(interfaceSurface, 450, 690, blits["pressedButtonFrame"]);
	DisplaySurface(interfaceSurface, 460, 700, blits["inventory"]);

	//pauza
	DisplaySurface(interfaceSurface, 600, 690, blits["button"]);
	if (downButton == b_pause)
		DisplaySurface(interfaceSurface, 600, 690, blits["pressedButtonFrame"]);
	DisplaySurface(interfaceSurface, 610, 700, blits["pause"]);

	//wyjście
	DisplaySurface(interfaceSurface, 750, 690, blits["button"]);
	if (downButton == b_exit)
		DisplaySurface(interfaceSurface, 750, 690, blits["pressedButtonFrame"]);
	DisplaySurface(interfaceSurface, 760, 700, blits["exit"]);

	//odświeżamy ekran
	SDL_Flip(screen);
	return true;
}

bool Interface::DrawCentre() {
	switch(activeScreen) {
		case s_world: {
			world->draw();
			return true;
			break;
		} case s_inventory: {
			world->draw();
			return inventoryScreen->Draw();
			break;
		}
	}
}

void Interface::OnMouseButtonDown(int x, int y, int button) {
	if (button == SDL_BUTTON_LEFT) {
		downButton = isInsideButton(x, y);
		switch (downButton) {
			case b_inventory:
			case b_pause:
			case b_menu:
			case b_exit: {
				Draw();
				break;
			}
		}
	}

	//przekazujemy kliknięcie do podklasy
	if (isInsideCentre(x, y)) {
		switch (activeScreen) {
			case s_inventory: {
				inventoryScreen->OnMouseButtonDown(x, y, button);
				break;
			} case s_world: {
				world->mouseClick(x, y, button);
			}
		}
	}
}

void Interface::OnMouseButtonUp(int x, int y, int button) {
	if (downButton == b_none && isInsideCentre(x, y)) {
		switch (activeScreen) {
			case s_inventory: {
				inventoryScreen->OnMouseButtonUp(x, y, button);
				break;
			}
			//HACK: Podniesienia przycisków nie są przekazywane do World
		}
		return;
	}

	if (button == SDL_BUTTON_LEFT) {
		Button upButton = isInsideButton(x, y);

		Draw();
		if (downButton != upButton) {
			upButton = b_none;
			downButton = b_none;
		} else {
			SDL_Event event;

			switch (downButton) {
				case b_inventory: {
					event.type = SDL_USEREVENT;
					event.user.code = ToggleInventory() ? e_pause : e_unpause;
					SDL_PushEvent(&event);
					break;
				} case b_pause: {
					event.type = SDL_USEREVENT;
					event.user.code = e_togglePause;
					SDL_PushEvent(&event);
					break;
				} case b_exit: {
					event.type = SDL_QUIT;
					SDL_PushEvent(&event);
					break;
				}
			}
			downButton = b_none;
		}
	}
}

bool Interface::ToggleInventory() {
	if (activeScreen == s_world) {
		activeScreen = s_inventory;
	} else if (activeScreen == s_inventory) {
		activeScreen = s_world;
	}
	DrawCentre();
	return activeScreen == s_inventory;
}

Interface::Button Interface::isInsideButton(int x, int y) {
	if (isPointInsideRect(x, y, 450, 690, 72, 70)) { //ekwipunek
		return b_inventory;
	} else if (isPointInsideRect(x, y, 600, 690, 72, 70)) { //pauza
		return b_pause;
	} else if (isPointInsideRect(x, y, 750, 690, 72, 70)) { //wyjście
		return b_exit;
	} else {
		return b_none;
	}
}

bool Interface::isInsideCentre(int x, int y) {
	//TODO: Chyba takie dopiero będą..., aktualnie 518x318
	return isPointInsideRect(x, y, 120, 80, 800, 600); // było 318x400
}
